//继承和多态
//继承：对共性的抽取，达到对代码的复用。继承关系 is a关系  子类is a 父类
//this super
//子类构造和父类构造

//多态：一种事物多种形态。完成同一个行为，不同对象去完成时会有不同的现象

//多态的实行条件：必须在继承体系下，
// 子类必须对父类的方法进行重写
//父类引用调用重写对象
//向上转型
//重写
//继承




class Animal {
    public String name;
    public int age;

    public void eat() {
        System.out.println(name + "eat");
    }

}

class Dog extends Animal{
    public String wing;//翅膀
    public void bark() {
        System.out.println(name + "wangwang");
    }

    @Override
    public void eat() {
        System.out.println(name + "吃狗粮");
    }

//重写需要满足三个条件：方法名称相同  参数列表相同 返回值相同
}

class Bird extends Animal {
    public void fly() {
        System.out.println(name + "fly");
    }
    //注释注解：表明当前方法是被重写的，加上去后会帮助我们检查重写方法是否写错
//    @Override
//    public void eat() {
//        System.out.println(name + "吃鸟粮");
//    }


    @Override
    public void eat() {
        System.out.println(name + "吃鸟粮");
    }

    //快捷键创建重写方法 右键 generate methonoverride
}


public class Test {
//理论上来说，等号两边的数据类型必须一致，否则会出错。但是有继承关系
// 的两个类就可以看成是一个类

    public static void function(Animal animal) {
        //对于animal，不能知道将来要引用的对象
        //当父类引用引用的对象不一样，表现出的行为不一样，就叫做多态
        //多态时一种思想，是在动态绑定前提下的
        animal.eat();
    }
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "十三月";
        Animal animal1 = dog;
        animal1.eat();

        Bird bird = new Bird();
        bird.name = "圆圆";
        Animal animal2 = bird;
        animal2.eat();
        function(animal2);
    }

    //动态绑定：在运行的时候，编译器帮助我们调用重写的子类方法
    //动态绑定的前提：向上转型  发生重写 通过父类引用调用父类和子类重名的重写的方法
    //在编译时，确实和我们猜测一样，调用的是父类的重写方法
    //但是在执行过程中，会调用子类的重写方法（这个过程就叫动态绑定） 动态--》运行

    //动态绑定是发生多态的前提

    //静态绑定：重载。在编译时已经确认调用的方法
    //动态绑定：重写，在运行的时候确认调用的方法
    public static  int add(int a,int b,int c) {
        return (a+b+c);
    }

    public static int add(int a,int b) {
        return a+b;
    }


   public static void func(Animal animal) {

   }
   public static  Animal func2(){

       return new Dog();
   }

    public static void main4(String[] args) {
       Dog dog = new Dog();
       func(dog);
    }
//向上转型的三种方式：直接赋值  方法传参  返回值
    public static void main3(String[] args) {
        Animal animal1 = new Dog();
        Animal animal2 = new Bird();
        animal1.name = "十三月";
        animal2.name = "圆圆";
//        animal1.bark();
//   父类没有bark（）方法，所以会报错，只能访问父类特有的成员属性和成员方法
//当我们发生向上转型之后，此时通过父类的引用只能访问父类自己的成员，不能访问子类特有的成员
//成员=成员属性+成员方法
    }

    public static void main2(String[] args) {
        Dog dog = new Dog();
        dog.name = "十三月";
        Animal animal = dog;

        Bird bird = new Bird();
        bird.name = "圆圆";
        Animal animal1 = bird;
    }

    public static void sway(MyValue myV1,MyValue myV2) {
//        int tmp = myV1.val;
        int tmp = myV1.getVal();
//        myV1.val = myV2.val;
        myV1.setVal(myV2.getVal());
//        myV2.val = tmp;
        myV2.setVal(tmp);

        //此处能够实现交换是因为通过引用去进行交换
        //形参和实参的指向相同，可以通过形参去修改实参指向的对象的成员属性，但是此时形参和实参都不会改变
        //因为形参和实参存储的内容都是数据
//封装：将数据设置成private，然后需要使用时使用set和get方法
    }
//    public static void sway(int a.int b) {
//        int tmp = a;
//        a = b;
//        b = tmp;
//    }

    //问题代码，记得回来补充调试，寻找原因
    public static void main1(String[] args) {
        MyValue myValue1 = new MyValue();
        myValue1.setVal(10);
        MyValue myValue2 = new MyValue();
        myValue1.setVal(20);
        sway(myValue1,myValue2);

    }
}

class MyValue {
//    public int val;
    private int val;

    public int getVal() {
        return val;
    }

    public void setVal(int val) {
        this.val = val;
    }
}




//重写注意事项：
//private修饰方法不能重写
//static修饰方法不能重写
//final修饰方法不能重写，此时这个方法被称作密封方法  final 修饰类 密封类  修饰变量 常量
//子类的访问修饰限定权限要大于父类的权限
//private<default<protected<public
//构造方法不能重写（构造方法名字要和类名相同
//重写和重载的区别

//重写---》在保留原有功能的基础上对功能进行拓展，不破坏原有功能


//多态---》动态绑定

//
//向上转型
// 优点让代码实现更加简单灵活
// 缺点不能调用子类特有方法

//向下转形









